import { formatTime } from '../../util/dayjs'
import _ from 'lodash'
import Reg from '../../../../global/Reg'
import md5 from 'blueimp-md5'
import { LoginPsdForm, LoginResponse, LoginSmsForm, RegisterForm, SmsType } from '../../../../global/types'
import { checkSms } from '../sms/logic'
import { Context } from 'koa'

export default {
	/** 检查手机号是否存在 */
	checkPhone,
	/** 注册用户 */
	register,
	/** 密码登录 */
	loginPsd,
	/** 短信登录 */
	loginSms,
	/** 修改语言 */
	changeLocale
}

/**
 * 插入登录记录并返回 token
 * @param ctx koa上下文
 * @param phone 用户手机号码
 * @returns Promise<token>
 */
const login = async (ctx: Context, phone: string, uid: string) => {
	// 生成token
	const userAgent = ctx.header['user-agent']
	const userIp = ctx.request.ip
	const createTime = formatTime()
	const token = md5(phone + userAgent + userIp + createTime)
	// 重新登录后将之前的 token 失效
	await ctx.db.update(`UPDATE login SET isVaild=0 WHERE phone=${phone} AND isVaild=1`)
	// 插入新登录记录
	await ctx.db.insert(
		`INSERT INTO login (uid, phone, userIp, userAgent, token) VALUES (${uid}, "${phone}", "${userIp}", "${userAgent}", "${token}")`
	)
	return token
}

async function checkPhone(ctx: Context) {
	const phone = ctx.query.phone as string
	if (!Reg.isPhone(phone)) return ctx.error('无效的手机号码')
	const res = await ctx.db.selectOne(`SELECT id FROM user WHERE phone=${phone}`)
	ctx.return(!!res)
}

async function register(ctx: Context) {
	const { phone, name, psd, code } = ctx.request.body as RegisterForm

	// 校验表单
	if (!Reg.isPhone(phone)) return ctx.error('无效的手机号码')
	if (!Reg.inLength(name, 2, 12)) return ctx.error('昵称应在2-12个字符之间')
	if (!Reg.inLength(psd, 6, 12)) return ctx.error('密码应在6-12个字符之间')
	if (!Reg.is6Num(code)) return ctx.error('无效的短信验证码')
	const isExistPhone = await ctx.db.selectOne(`SELECT * FROM user WHERE phone="${phone}"`)
	if (isExistPhone) return ctx.error('该手机号已被注册')

	const isPass = await checkSms(ctx, phone, code, SmsType.register)
	if (!isPass) return
	await ctx.db.insert(`INSERT INTO user (phone, name, psd) VALUES ("${phone}", "${name}", "${psd}")`)
	ctx.success(`成功注册用户${name}`)
}

async function loginPsd(ctx: Context) {
	const { phone, psd } = ctx.request.body as LoginPsdForm

	// 校验表单
	if (!Reg.isPhone(phone)) return ctx.error('无效的手机号码')
	if (!Reg.inLength(psd, 6, 12)) return ctx.error('密码应在6-12个字符之间')
	const userInfo = await ctx.db.selectOne(
		`SELECT id, phone, name, locale FROM user WHERE phone="${phone}" AND psd="${psd}"`
	)
	if (!userInfo) return ctx.error('手机号码或密码错误')

	const token = await login(ctx, phone, userInfo.id)
	const data: LoginResponse = { ...userInfo, token }
	ctx.success({ data, msg: '登录成功' })
}

async function loginSms(ctx: Context) {
	const { phone, code } = ctx.request.body as LoginSmsForm

	if (!Reg.isPhone(phone)) return ctx.error('无效的手机号码')
	if (!Reg.is6Num(code)) return ctx.error('无效的手机验证码')

	const isPass = await checkSms(ctx, phone, code, SmsType.login)
	if (!isPass) return
	const userInfo = await ctx.db.selectOne(`SELECT id, phone, name, locale createTime FROM user`)
	const token = await login(ctx, phone, userInfo.id)
	if (!userInfo) return ctx.error('不存在的用户')
	const data: LoginResponse = { ...userInfo, token }
	ctx.success({ data, msg: '登录成功' })
}

async function changeLocale(ctx: Context) {
	const { locale } = ctx.request.body
	if (!locale) return ctx.error('缺少语言参数')
	if (!['zhCN', 'enUS'].includes(locale)) return ctx.error('无效的语言参数')
	await ctx.db.update(`UPDATE user SET locale='${locale}' WHERE id=${ctx.userInfo!.id}`)
	ctx.success('成功修改语言')
}
